feat(shell,open): add piping, multi-instance, and cross-platform support#282
feat(shell,open): add piping, multi-instance, and cross-platform support#282
Conversation
Enhance brev shell and brev open commands with composability features. Shell improvements: - Add -c flag to run commands non-interactively - Support @filepath syntax to run local scripts remotely - Accept multiple instances or pipe from stdin - Output instance names for chaining Open improvements: - Support multiple instances (opens each in separate window) - Add terminal and tmux editor options - Add Terminal.app support on macOS - Fix WSL exec format error on Windows - Accept instances from stdin for piping Examples: brev shell my-instance -c "nvidia-smi" brev shell my-instance -c @setup.sh brev create my-instance | brev shell -c "nvidia-smi" brev open my-instance tmux brev create my-cluster --count 3 | brev open cursor
- Fix gofumpt formatting - Wrap external package errors with breverrors.WrapAndTrace Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Manual QA Results ✅Build & Static Analysis:
Test Plan Verification:
Notes:
|
pkg/cmd/open/open.go
Outdated
| return breverrors.WrapAndTrace(err) | ||
| } | ||
| } | ||
| if lastErr != nil { |
There was a problem hiding this comment.
in the case of an error with more than one instance it doesn't look like we actually ever return the error?
pkg/cmd/open/open.go
Outdated
| setupDoneString = "------ Done running execs ------" | ||
| // Validate editor flag if provided | ||
| if editor != "" && !isEditorType(editor) { | ||
| return breverrors.NewValidationError(fmt.Sprintf("invalid editor: %s. Must be 'code', 'cursor', 'windsurf', or 'tmux'", editor)) |
There was a problem hiding this comment.
terminal is also valid?
pkg/cmd/shell/shell.go
Outdated
| if (stat.Mode() & os.ModeCharDevice) == 0 { | ||
| // Stdin is piped, read instance names (one per line) | ||
| scanner := bufio.NewScanner(os.Stdin) | ||
| for scanner.Scan() { |
There was a problem hiding this comment.
do we need to check for errors (scanner.Err() != nil) ?
pkg/util/util.go
Outdated
|
|
||
| cmd := exec.Command("cmd.exe", cmdArgs...) // #nosec G204 | ||
| output, err := cmd.CombinedOutput() | ||
| return output, breverrors.WrapAndTrace(err) |
There was a problem hiding this comment.
missing a nil check on err?
pkg/util/util.go
Outdated
|
|
||
| func runWindsurfCommand(windsurfpath string, args []string) ([]byte, error) { | ||
| // In WSL, Windows .exe files need to be run through cmd.exe | ||
| if isWSL() && (strings.HasSuffix(windsurfpath, ".exe") || strings.HasPrefix(windsurfpath, "/mnt/")) { |
There was a problem hiding this comment.
runVsCodeCommand, runCursorCommand, and runWindsurfCommand seem to have the same structure, extract a common method that takes the path as an arg?
func runEditorCommand(path string, args []string) ([]byte, error) {
if isWSL() && (strings.HasSuffix(path, ".exe") || strings.HasPrefix(path, "/mnt/")) {
return runWindowsExeInWSL(path, args)
}
cmd := exec.Command(path, args...) // #nosec G204
res, err := cmd.CombinedOutput()
if err != nil {
return nil, breverrors.WrapAndTrace(err)
}
return res, nil
}
pkg/cmd/open/open.go
Outdated
| } | ||
|
|
||
| func openTerminal(sshAlias string, path string, store OpenStore) error { | ||
| _ = store // unused parameter required by interface |
There was a problem hiding this comment.
I think you can move these dashes in to the signature, so you don't need the declaration, e.g.
func openTerminal(sshAlias string, _ string, _ OpenStore) error {
| cmd.Flags().BoolVarP(&runRemoteCMD, "remote", "r", true, "run remote commands") | ||
| cmd.Flags().StringVarP(&directory, "dir", "d", "", "override directory to launch shell") |
There was a problem hiding this comment.
these are safe to remove?
There was a problem hiding this comment.
Yes, these are safe to remove - they were dead code:
--remote/-r: The variablerunRemoteCMDwas declared but never actually used anywhere in the code--dir/-d: Thedirectoryparameter was passed torunSSH, but that function immediately discarded it with_in its signature:func runSSH(_ *entity.Workspace, sshAlias, _ string) error
Neither flag had any functional effect.
Add implemented features for brev shell and brev open: Shell enhancements: - Non-interactive -c flag for scripted execution - @filepath syntax to run local scripts remotely - Multi-instance support (run on multiple instances) - Stdin piping from brev create/ls - Output instance names for command chaining Open enhancements: - Multiple editor options (vscode, cursor, vim, terminal, tmux) - Multi-instance support (opens each in separate window) - Cross-platform fixes (macOS Terminal.app, WSL) - Stdin piping from brev create Also expands skills documentation explaining why they matter for agentic use cases.
- shell: interactive, no stdin/stdout - shell -c: accepts instance names from stdin, outputs command stdout/stderr
Create new 'brev exec' command for non-interactive command execution: - Run commands on one or more instances - Support @filepath syntax to run local scripts remotely - Accept instance names from stdin for piping - Output instance names for command chaining Simplify 'brev shell' to be interactive only: - Remove -c flag (use 'brev exec' instead) - Single instance argument required - Keep --host flag for host SSH Update PRD to document the new command separation.
open.go: - Add 'terminal' to valid editors in error message - Use multierror for better multi-instance error aggregation - Add scanner error check for stdin reading util.go: - Extract common runEditorCommand helper for WSL compatibility - Simplify runVsCodeCommand, runCursorCommand, runWindsurfCommand
Enable chaining with brev open by outputting instance names: brev create my-gpu | brev open cursor | brev exec 'pip install torch' Only outputs when stdout is piped, keeping interactive use clean.
Coding agents prefer CLIs: text-native, self-documenting, composable, and already learned from training data. Positions Brev CLI as the default for autonomous GPU workflows.
Summary
prd: https://docs.google.com/document/d/1pYYR1nfcfJi9kCtcxiY5DINYjGxXwnO6zh7JdtmGBTU/edit?tab=t.0#heading=h.oyak6y4d25ei
Enhance
brev shellandbrev opencommands with composability features for scriptable workflows.Shell Improvements
-cflag to run commands non-interactively@filepathsyntax to run local scripts on remote instancesOpen Improvements
terminalandtmuxeditor optionsExamples
Test plan
brev shell instance -c "cmd"runs command and returnsbrev shell instance -c @script.shruns local script remotelybrev open instance tmuxopens tmux session